package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/yosssi/gmq/mqtt"
	"github.com/yosssi/gmq/mqtt/client"
	"io/ioutil"
	"net/http"
	"net/url"
	"recharge/logger"
	"strconv"
	"strings"
	"time"
)

type Device struct {
	ID           int
	EquipmentNum string
	State        string //状态
	SocketNums   string
	UpdatedAt    time.Time `gorm:"column:updated_at"`
}

func (this *Device) TableName() string {
	return "equipment"
}

type DeviceNumber struct {
	ID            int
	EID           string `gorm:"column:eid;"`
	State         int    //状态
	Number        string
	DisplayNumber string
	UpdatedAt     time.Time `gorm:"column:updated_at"`
}

func (this *DeviceNumber) TableName() string {
	return "equipment_nums"
}

//设备指令
type DeviceCommand struct {
	ExecuteStatus int `json:"executeStatus"`
	MsgType       int `json:"msgType"`
	Action        int `json:"action"`
	ChannelID     int `json:"channelID"` //第几路插座
	MaxTime       int `json:"maxTime"`   //多久后关闭 单位s
	MsgSN         int `json:"msgSN"`
}

//打开设备电源
func OpenDevice(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	channelIDStr := v.Get("channelID")
	if channelIDStr == "" {
		JsonResponse(w, 404, "线路不存在！", map[string]interface{}{})
		return
	}
	channelID, err := strconv.Atoi(channelIDStr)
	if err != nil {
		JsonResponse(w, 400, "线路错误！", map[string]interface{}{})
		return
	}
	maxTimeStr := v.Get("maxTime")
	if maxTimeStr == "" {
		JsonResponse(w, 404, "时长错误！", map[string]interface{}{})
		return
	}
	maxTime, err := strconv.Atoi(maxTimeStr)
	if err != nil {
		JsonResponse(w, 400, "时长错误！", map[string]interface{}{})
		return
	}
	err = GBStartRecharge(did, channelID, maxTime, ACTION_OPEN, MSG_TYPE_CONTROL)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	JsonResponse(w, 200, "action success", map[string]interface{}{})
	return
}

//打开设备电源
func SetDeviceNumber(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	numberS := v.Get("number")
	if numberS == "" {
		JsonResponse(w, 404, "线路不存在！", map[string]interface{}{})
		return
	}
	number, err := strconv.Atoi(numberS)
	if err != nil {
		JsonResponse(w, 400, "线路错误！", map[string]interface{}{})
		return
	}
	newNumberS := v.Get("new_number")
	if newNumberS == "" {
		JsonResponse(w, 404, "新线路不存在！", map[string]interface{}{})
		return
	}
	newNumber, err := strconv.Atoi(newNumberS)
	if err != nil {
		JsonResponse(w, 400, "新线路错误！", map[string]interface{}{})
		return
	}
	err = GBSetDeviceNumber(did, int64(number), int64(newNumber))
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	JsonResponse(w, 200, "action success", map[string]interface{}{})
	return
}

func GetInt32(k string, v url.Values) int32 {
	val := v.Get(k)
	if val == "" {
		return 0
	}
	kI, err := strconv.Atoi(val)
	if err != nil {
		logger.Log.Error(err)
		return 0
	}
	return int32(kI)
}

//设置设备参数
func SetDevice(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	ratedpower := GetInt32("ratedpower", v)
	maxChargeTime := GetInt32("maxChargeTime", v)
	periodTime := GetInt32("periodTime", v)
	continueTime := GetInt32("continueTime", v)
	continuePower := GetInt32("continuePower", v)
	endTime := GetInt32("endTime", v)
	minPower := GetInt32("minPower", v)
	//设置设备初始参数
	err := GBRspClientInfo(did, ratedpower, maxChargeTime, periodTime, continueTime, continuePower, endTime, minPower)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	JsonResponse(w, 200, "action success", map[string]interface{}{})
	return
}

//获取设备插座列表
func GetDeviceSockets(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	//获取设备插座列表
	err := GBGetDeviceSocketList(did, 0, 0, ACTION_OPEN, MSG_TYPE_CONTROL)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	JsonResponse(w, 200, "action success", map[string]interface{}{})
	return
}

//关闭设备电源
func CloseDevice(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	channelIDStr := v.Get("channelID")
	if channelIDStr == "" {
		JsonResponse(w, 404, "线路不存在！", map[string]interface{}{})
		return
	}
	channelID, err := strconv.Atoi(channelIDStr)
	if err != nil {
		JsonResponse(w, 400, "线路错误！", map[string]interface{}{})
		return
	}
	maxTimeStr := v.Get("maxTime")
	if maxTimeStr == "" {
		JsonResponse(w, 404, "时长错误！", map[string]interface{}{})
		return
	}
	maxTime, err := strconv.Atoi(maxTimeStr)
	if err != nil {
		JsonResponse(w, 400, "时长错误！", map[string]interface{}{})
		return
	}
	err = GBEndRecharge(did, channelID, maxTime, ACTION_CLOSE, MSG_TYPE_CONTROL)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	JsonResponse(w, 200, "action success", map[string]interface{}{})
	return
}

//订阅设备
func SubscribeDevice(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	err := BGSubscribeDeviceByID(did)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	logger.Log.Debug("subscribe", did, "success")
	JsonResponse(w, 200, "subscribe success", map[string]interface{}{})
	return
}

//取消订阅设备
func UnSubscribeDevice(w http.ResponseWriter, r *http.Request) {
	v := r.URL.Query()
	did := v.Get("deviceID")
	if did == "" {
		JsonResponse(w, 404, "设备号不存在！", map[string]interface{}{})
		return
	}
	err := UnSubscribeDeviceByID(did)
	if err != nil {
		JsonResponse(w, 500, err.Error(), map[string]interface{}{})
		return
	}
	logger.Log.Debug("unsubscribe", did, "success")
	JsonResponse(w, 200, "unsubscribe success", map[string]interface{}{})
	return
}

//订阅设备
func SubscribeDeviceByID(did string) error {
	err := cli.Subscribe(&client.SubscribeOptions{
		SubReqs: []*client.SubReq{
			&client.SubReq{
				TopicFilter: []byte(fmt.Sprintf("/dev/%s", did)),
				QoS:         mqtt.QoS0,
				// 接收设备消息
				Handler: func(topicName, message []byte) {
					logger.Log.Debug("[设备回传信息]", string(topicName), string(message))
					h := string(message)
					b, _ := hex.DecodeString(h)
					var c DeviceCommand
					err := json.Unmarshal(b, &c)
					if err != nil {
						logger.Log.Warning(string(b))
						logger.Log.Error(err)
						return
					}
					deviceID := strings.ReplaceAll(string(topicName), "/dev/", "")
					logger.Log.Debug(string(b))
					if c.MsgType == MSG_TYPE_CONTROL { //控制反馈消息
						switch c.ExecuteStatus {
						case EXECUTE_STATUS_NOTIFY:
							//当充电结束通知的消息 TODO
							var r http.Request
							_ = r.ParseForm()
							r.Form.Add("deviceID", deviceID)
							r.Form.Add("channelID", fmt.Sprintf("%d", c.ChannelID))
							bodystr := strings.TrimSpace(r.Form.Encode())
							request, err := http.NewRequest("GET", DEVICE_CALL_BACK_URL, strings.NewReader(bodystr))
							if err != nil {
								logger.Log.Error(err)
								return
							}
							request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
							var resp *http.Response
							resp, err = http.DefaultClient.Do(request)
							if err != nil {
								logger.Log.Error(err)
								return
							}
							defer func() {
								_ = resp.Body.Close()
							}()
							b, err := ioutil.ReadAll(resp.Body)
							if err != nil {
								logger.Log.Error(err)
								return
							}
							logger.Log.Info(string(b))
						case EXECUTE_STATUS_SUCCESS:
							//通知充电桩的消息 成功
							if c.Action == ACTION_OPEN {
								//电源打开成功 TODO 处理逻辑
							} else if c.Action == ACTION_CLOSE {
								//电源关闭成功 TODO 处理逻辑
							}
						case EXECUTE_STATUS_ERROR:
							//通知充电桩的消息 失败
							if c.Action == ACTION_OPEN {
								//电源打开失败 TODO 处理逻辑
							} else if c.Action == ACTION_CLOSE {
								//电源关闭失败 TODO 处理逻辑
							}
						default:
							logger.Log.Error("处理异常:", string(b))
						}
					}
					if c.MsgType == MSG_TYPE_QUERY { //查询设备 消息
						switch c.ExecuteStatus {
						case EXECUTE_STATUS_NOTIFY:
							// 主动ping数据
						case EXECUTE_STATUS_SUCCESS:
							//查询设备信息成功

						case EXECUTE_STATUS_ERROR:
							//查询设备信息 失败
						default:
							logger.Log.Error("处理异常:", string(b))
						}
					}
				},
			},
		},
	})
	return err
}

//取消订阅设备
func UnSubscribeDeviceByID(did string) error {
	err := cli.Unsubscribe(&client.UnsubscribeOptions{
		TopicFilters: [][]byte{
			[]byte(fmt.Sprintf("/dev/%s", did)),
		},
	})
	return err
}
